<template>
  <div class="hello" style="text-align:left"> 
    <ConnDialog :show="showConnDialog" ref="connDialog"
      @callback="connDialogCallback" :tabLength="tabArr.length" @update:show="val=>showConnDialog=val"></ConnDialog>
    <el-tabs tab-position="top" style="height: auto; " class="demo-tabs" :addable="false"
       :closable="true" editable @edit="tabsEdit"
       v-model="tabActive">
      <el-tab-pane :label="item.label" v-for="item in tabArr" :name="item.name" :key="item.name">
        <el-row :gutter="2">
          <component :is="comlist.filter(o => o.key == item.conn.type)[0].value"
            :show="item.showDesign" :dbName="item.conn.dbname ||item.conn.username" 
            :tableName="item.designTableName" :comments="item.designTableComments" :dbConnStr="item.conn.DbConnStr"
             @update:show="val=>{item.showDesign=val;connDialogCallback(item.conn, true)}" ></component>
          <CodeMirrorDialog :show="item.showCMDialog" :content="item.cmdContent" :dbType="item.conn.type"
          :dbConnStr="item.conn.DbConnStr" @update:show="val=>item.showCMDialog=val"
            :keywords="item.keywords"></CodeMirrorDialog>
          <el-col :sm="8">
            <el-row style="margin: 10px">
              <el-button type="primary" size="small" @click="connDialogCallback(item.conn, true)">刷新</el-button>
              <el-button type="primary" size="small" @click="tableDesign({})">新建表</el-button>
            </el-row>
            <el-scrollbar :height="leftHeight" always>
              <el-card class="box-card designlist">
                <el-collapse v-model="item.collapase">
                  <el-collapse-item :title="`表(${item.table.length})`" name="1">
                     <el-table :data="item.table" size="small" highlight-current-row :border="true" empty-text="无数据">
                        <el-table-column type="index" width="42" align="center" />
                        <el-table-column label="操作" width="100" align="center">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="tableDesign(scope.row)" :disabled="scope.row.TABLE_NAME == 'sqlite_sequence'">编辑</el-button>
                                <el-button type="text" size="small" @click="dropObject('table', scope.row.TABLE_NAME)" :disabled="scope.row.TABLE_NAME == 'sqlite_sequence'">删除</el-button>
                            </template>
                        </el-table-column>
                        <el-table-column prop="TABLE_NAME" label="名称" :show-overflow-tooltip="true">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="choseTable(scope.row.TABLE_NAME)">{{scope.row.TABLE_NAME}}</el-button>
                            </template>
                        </el-table-column>
                    </el-table>
                  </el-collapse-item>
                  <el-collapse-item :title="`视图(${item.view.length})`" name="2">
                     <el-table :data="item.view" size="small" highlight-current-row :border="true" empty-text="无数据">
                        <el-table-column type="index" width="42" align="center" />
                        <el-table-column label="操作" width="100" align="center">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="showDefine('VIEW', scope.row.TABLE_NAME)">编辑</el-button>
                                <el-button type="text" size="small" @click="dropObject('view', scope.row.TABLE_NAME)">删除</el-button>
                            </template>
                        </el-table-column>
                        <el-table-column prop="TABLE_NAME" label="名称" :show-overflow-tooltip="true">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="choseTable(scope.row.TABLE_NAME)">{{scope.row.TABLE_NAME}}</el-button>
                            </template>
                        </el-table-column>
                    </el-table>
                  </el-collapse-item>
                  <el-collapse-item :title="`函数(${item.func.length})`" name="3" v-if="item.conn.type != 'Sqlite'">
                     <el-table :data="item.func" size="small" highlight-current-row :border="true" empty-text="无数据">
                        <el-table-column type="index" width="42" align="center" />
                        <el-table-column label="操作" width="100" align="center">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="showDefine('FUNCTION', scope.row.TABLE_NAME)">编辑</el-button>
                                <el-button type="text" size="small" @click="dropObject('function', scope.row.TABLE_NAME)">删除</el-button>
                            </template>
                        </el-table-column>
                        <el-table-column prop="TABLE_NAME" label="名称" :show-overflow-tooltip="true" />
                    </el-table>
                  </el-collapse-item>
                  <el-collapse-item :title="`过程(${item.proc.length})`" name="4" v-if="item.conn.type != 'Sqlite'">
                     <el-table :data="item.proc" size="small" highlight-current-row :border="true" empty-text="无数据">
                        <el-table-column type="index" width="42" align="center" />
                        <el-table-column label="操作" width="100" align="center">
                            <template #default="scope">
                                <el-button type="text" size="small" @click="showDefine('PROCEDURE', scope.row.TABLE_NAME)">编辑</el-button>
                                <el-button type="text" size="small" @click="dropObject('procedure', scope.row.TABLE_NAME)">删除</el-button>
                            </template>
                        </el-table-column>
                        <el-table-column prop="TABLE_NAME" label="名称" :show-overflow-tooltip="true" />
                    </el-table>
                  </el-collapse-item>
                </el-collapse>
              </el-card>
            </el-scrollbar>
          </el-col>
          <el-col :span="16">
            <div style="padding: 5px 32px">
                <el-button type="primary" size="small"  @click="RunSql(item)">运行</el-button>
            </div>
            <div>
              <CodeMirrorCore :content="item.content" mode="text/x-sql" :ref="'code' + item.name"
               :dbType="item.conn.type" :keywords="item.keywords" :height="editorHeight"></CodeMirrorCore>
            </div>
          </el-col>
        </el-row>
      </el-tab-pane>
    </el-tabs>
    
    <el-drawer v-model="showDrawer" title="输出" direction="btt" size="60%" :with-header="false">
          <el-tabs tab-position="top" style="height: auto; " class="demo-tabs" :addable="false"
          :closable="false" v-model="drawerActive" @tab-change="logAreaResize">
              <el-tab-pane :label="'Log'" :name="'log'">
                <textarea v-model="logsFormat" readonly id="logArea"
                  style="width:99%;height:240px;font: 12px '宋体';border: 1px solid #ddd;outline:none;"></textarea>
              </el-tab-pane>
              <el-tab-pane v-for="item in drawerTables" :label="item.label" :name="item.name" :key="item.name">
                  <el-row style="margin:10px">
                    <el-dropdown>
                      <el-button type="text" size="small">操作</el-button>
                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item @click="toSqls('insert')">to insert sql</el-dropdown-item>
                          <el-dropdown-item @click="toSqls('update')">to update sql</el-dropdown-item>
                          <el-dropdown-item @click="toSqls('delete')">to delete sql</el-dropdown-item>
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </el-row>
                  <el-table :data="item.data" size="small" height="auto" empty-text="无数据" tooltip-effect="dark"
                    highlight-current-row :border="true" ref="refTable">
                    <el-table-column type="index" width="50" align="center"  />
                    <el-table-column type="selection" width="55" align="center"  />
                    <el-table-column label="操作" width="120">
                      <template #default="scope">
                        <el-dropdown>
                          <el-button type="text" size="small">操作</el-button>
                          <template #dropdown>
                            <el-dropdown-menu>
                              <el-dropdown-item @click="toSql(scope.row, 'insert')">to insert sql</el-dropdown-item>
                              <el-dropdown-item @click="toSql(scope.row, 'update')">to update sql</el-dropdown-item>
                              <el-dropdown-item @click="toSql(scope.row, 'delete')">to delete sql</el-dropdown-item>
                            </el-dropdown-menu>
                          </template>
                        </el-dropdown>
                      </template>
                    </el-table-column>
                    <el-table-column v-for="col in item.columns" :key="col" :prop="col.name" :label="col.name" width="150" :show-overflow-tooltip="true" />
                  </el-table>
                  <el-row style="margin:5px 0">
                    <el-alert title="超出50行不会加载，请修改查询条件" type="success" :closable="false" />
                  </el-row>
              </el-tab-pane>
          </el-tabs>
    </el-drawer>

  </div>
</template>

<script setup>
import ConnDialog from '/src/components/ConnDialog'
import CodeMirrorCore from '/src/components/CodeMirrorCore'
import CodeMirrorDialog from '/src/components/CodeMirrorDialog'
import OracleDesign from '/src/components/OracleDesign'
import SqliteDesign from '/src/components/SqliteDesign'
import SqlserverDesign from '/src/components/SqlserverDesign'
import MysqlDesign from '/src/components/MysqlDesign'
import {post} from '/src/utils/http'
import { ElMessage } from 'element-plus'

import { computed, reactive, watch,defineProps, defineEmits, onMounted, toRefs, nextTick, ref, getCurrentInstance  } from 'vue'

const props = defineProps({
    msg:String,
})

const { msg } = toRefs(props)

//const emit = defineEmits(['callback'])

const ctx = getCurrentInstance().ctx

const comlist = [
  { key: 'Oracle', value: OracleDesign},
  { key: 'Sqlite', value: SqliteDesign }, 
  { key: 'Sqlserver', value: SqlserverDesign },
  { key: 'Mysql', value: MysqlDesign }
]

const showConnDialog = ref(true)
const tabActive = ref('')
const tabArr = ref([])
const currentTab = computed(() => tabArr.value.filter(o => o.name == tabActive.value)[0])
const currentCM = computed(() => ctx._.refs['code' + currentTab.value.name][0])

const showDrawer = ref(false)
const drawerActive = ref('log')
const logs = ref([])
const logsFormat = computed(() => logs.value.join('\n'))
const drawerTables = ref([])


function connDialogCallback(conn, onlyRefresh) {
  var param = {
    DbName:  conn.dbname || conn.username,
    TABLE_NAME: '',
    DbType: conn.type,
    DbConnStr: conn.DbConnStr,
    rows: 10000
  }
  var tab = currentTab.value
  post(`/api/${param.DbType}/GetTables`, param).then((res) => {
    if(res && res.rows.length > -1) { 
      if(!onlyRefresh) {
        tab = { 
          label: conn.name,
          name: new Date().getTime().toString(),
          conn: conn,
          content: '',
          columns: [],
          data: [],

          collapase: ['1'],
          table: [],
          view: [],
          proc: [],
          func: [],
          keywords: {},
          showDesign: false,
          designTableName: '',
          designTableComments: '',
          showCMDialog: false,
          cmdContent: '',
        }
        
        tabArr.value.push(tab)
        tabActive.value = tab.name
      }
      
      tab.table = res.rows.filter(o => o.TABLE_TYPE == 'TABLE')
      tab.view = res.rows.filter(o => o.TABLE_TYPE == 'VIEW')
      tab.proc = res.rows.filter(o => o.TABLE_TYPE == 'PROCEDURE')
      tab.func = res.rows.filter(o => o.TABLE_TYPE == 'FUNCTION')
      tab.keywords = {}
      for(var i in res.rows) { 
          tab.keywords[res.rows[i].TABLE_NAME] = []
      }

      showConnDialog.value = false
      logs.value = [...logs.value, '刷新列表']
      dispatchEvent(new Event('resize'))
    }
  })
}
function tableDesign(row){
  currentTab.value.designTableName = row.TABLE_NAME
  currentTab.value.designTableComments = row.COMMENTS
  currentTab.value.showDesign = true
}
function choseTable(table) {
  if(currentTab.value.conn.type == 'Mysql')
    currentCM.value.append(`select * from \`${table}\``)
  else 
    currentCM.value.append(`select * from "${table}"`)
}
function dropObject(type, name) {
  if(currentTab.value.conn.type == 'Mysql')
    currentCM.value.append(`drop ${type} \`${name}\``)
  else 
    currentCM.value.append(`drop ${type} "${name}"`)
}
function showDefine(type, name){
  var tab = currentTab.value
  var param = { 
    DbConnStr: tab.conn.DbConnStr, 
    DbName: tab.conn.username,
    DbType: tab.conn.type, 
    Type: type,
    Name: name,
  }
  logs.value = [...logs.value, `正在加载${name}...`]
  post(`/api/${param.DbType}/GetMetaData`, param).then((res) => {
    tab.cmdContent = res.data
    logs.value = [...logs.value, res.msg]
    tab.showCMDialog = true
  })
}
function tabsEdit(name, action){
  if(action =='add'){
    showConnDialog.value = true
  }
  if(action=='remove') {
    var arr = tabArr.value
    var index = arr.indexOf(arr.filter((o, i) => o.name == name)[0])
    if(tabActive.value != name) {
      arr.splice(index,1)
    } else if(arr.length > 1) {
      //关闭当前选项卡，是否处于最后一个
      tabActive.value = arr[index + 1 == arr.length ? arr.length-2 : index+1].name
      arr.splice(index,1)
    }
  }
}
function RunSql(item) {
  var sql = currentCM.value.getSelectionOrValue()

  var rx = /(?!;|$)[^;"]*(("[^"]*")[^;"]*)*/g
  var sqls = sql.match(rx)
  sqls = sqls.map(o => o.replace(/go/gi,'').trim())
              .filter(o => o.length > 0 && !o.startsWith('--'))

  console.log(sql)
  var param = { 
    DbConnStr: item.conn.DbConnStr, 
    DbName: item.conn.dbname ||item.conn.username,
    DbType: item.conn.type, 
    sqls
  }
  post(`/api/${param.DbType}/RunSql`, param).then((res) => {
    //连接成功
    logs.value = [...logs.value,...res.logs]
    drawerActive.value = 'log'
    drawerTables.value = []
    showDrawer.value = true

    if(res && res.flag && res.tables && res.tables.length > 0) { 
      drawerTables.value = res.tables.map((o,i)=> {
        return {
          label: `结果${i+1}`,
          name: `result${i+1}`,
          columns: o.columns,
          data: o.data
        }
      })
      drawerActive.value = drawerTables.value[drawerTables.value.length-1].name
    }

    nextTick(() => {
      if(sqls.map(o => o.toLowerCase())
        .filter(o => o.startsWith('create') || o.startsWith('drop') || o.startsWith('alter')).length > 0) {
          connDialogCallback(currentTab.value.conn, true)
        }
    })
  })
}
function toSqls(type) {
  var rows = ctx._.refs.refTable[0].getSelectionRows()
  if(rows.length > 0){
      toSql(rows, type)
  }
}
function toSql(obj, type) {
  var rows = Array.isArray(obj) ? obj: [obj]
  var sql = ''
  if(type == 'insert'){
    rows.forEach(row => {
      if(currentTab.value.conn.type == 'Oracle')
        sql += `insert into "table1" (${Object.keys(row).map(o => `"${o}"`).join(', ')})
values (${Object.values(row).map(o => o === null ? 'null' : `"${o.toString().replace(/"/g, '\\"')}"`)});\n`
      else
        sql += `insert into table1 (${Object.keys(row).map(o => `${o}`).join(', ')})
values (${Object.values(row).map(o => o === null ? 'null' : `"${o.toString().replace(/"/g, '\\"')}"`)});\n`

    })
    currentCM.value.append(sql)
    ElMessage({ 
      message: '已生成到SQL编辑器',
      type: 'success',
    })
  }
  if(type == 'update'){
    rows.forEach(row => {
      if(currentTab.value.conn.type == 'Oracle')
        sql += `update "table1" set ${Object.keys(row).map(o => row[o] === null ? `"${o}"=null` :  `"${o}"="${row[o].toString().replace(/"/g, '\\"')}"`).join(', ')}
where ${Object.keys(row).map(o => row[o] === null ? `"${o}" is null` :  `"${o}"="${row[o].toString().replace(/"/g, '\\"')}"`).join(' and ')};\n`
      else
        sql += `update table1 set ${Object.keys(row).map(o => row[o] === null ? `${o}=null` :  `${o}="${row[o].toString().replace(/"/g, '\\"')}"`).join(', ')}
where ${Object.keys(row).map(o => row[o] === null ? `${o} is null` :  `${o}="${row[o].toString().replace(/"/g, '\\"')}"`).join(' and ')};\n`

    })
    currentCM.value.append(sql)
    ElMessage({ 
      message: '已生成到SQL编辑器',
      type: 'success',
    }) 
  }
  if(type == 'delete'){
    rows.forEach(row => {
      if(currentTab.value.conn.type == 'Oracle')
        sql += `delete from "table1" where ${Object.keys(row).map(o => row[o] === null ? `"${o}" is null` :`"${o}"="${row[o].toString().replace(/"/g, '\\"')}"`).join(' and ')};\n`
      else
        sql += `delete from table1 where ${Object.keys(row).map(o => row[o] === null ? `${o} is null` :`${o}="${row[o].toString().replace(/"/g, '\\"')}"`).join(' and ')};\n`
    })
    currentCM.value.append(sql)
    ElMessage({ 
      message: '已生成到SQL编辑器',
      type: 'success',
    }) 
  }
}

function logAreaResize() {
  setTimeout(() => {
    var a = document.getElementById('logArea')
    a.scrollTop = a.scrollHeight
  }, 200)
}

const leftHeight = ref(400)
const editorHeight = ref(380)

window.addEventListener('resize', function(){
  var all = window.innerHeight
  leftHeight.value = all - 150
  editorHeight.value = all - 120
})

</script>

<style>
body{
  font-size:12px
}
body::-webkit-scrollbar{
  display: none;
}
.designlist .el-link {
  margin-right: 8px;
}

.table-container .el-table .caret-wrapper {
  height: 22px;
  line-height: 22px;
}

.el-table{
   --el-table-border: 1px solid #ddd !important;
}
 .el-table td, .el-table th.is-leaf {
   border-bottom: 1px solid #ddd !important;
 }
 .el-table--border, .el-table--group {
   border: 1px solid #ddd !important;
 }
</style>